﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Kinect_Interface_Prototype_1.Folder_Control;
using System.IO;
using Microsoft.VisualBasic.FileIO;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using Kinect_Interface_Prototype_1.Voice_Commands;
using WinPoint = System.Windows.Point;

namespace Kinect_Interface_Prototype_1.Interface_Design
{
    public partial class SettingsForm : Form
    {
        private string imageFolder = Constants.InterfaceImagesFolder;

        private List<string> acceptedImageTypes = new List<string> { ".png", ".jpg"};
        private string startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);

        private IniFile settingsINI;
        private StartupProgram MainProgram;
        private OpenFileDialog browseFileDialog = new OpenFileDialog();
        private OpenFileDialog browseImageDialog = new OpenFileDialog();

        private System.Windows.Controls.Canvas gestureBoxCanvas;
        private Dictionary<GestureRectangleType,GestureRectangleControl>  gestureRectangles
                                                    = new Dictionary<GestureRectangleType, GestureRectangleControl>();

        // General
        private LargeCheckBox gestureControlCheckBox;
        private LargeCheckBox mouseControlCheckBox;
        private LargeCheckBox voiceCommandsAtStartCheckBox;
        private LargeCheckBox showSkeletalTrackingCheckBox;

        // Voice Commands
        private LargeCheckBox enabledVoiceCommandCheckBox;

        private List<CustomApp> customApps = new List<CustomApp>();
        private List<VoiceCommandControl> voiceCommandControls = new List<VoiceCommandControl>();

        public SettingsForm(StartupProgram program)
        {
            InitializeComponent();
            InitializeApplicationDockSettings();
            InitializeScrollBars();
            InitializeCheckBoxes();
            InitializeGestureBoxes();

            MainProgram = program;
            MainProgram.AddSystemButtons(this); // Add the close, maximize, and minimize buttons

            settingsINI = new IniFile(Constants.SettingsINI);
            readSettingsFromINI();

            
        }

        private void InitializeGestureBoxes()
        {
            gestureBoxCanvas = new System.Windows.Controls.Canvas();
            gestureBoxCanvas.Width = 400;
            gestureBoxCanvas.Height = 280;
            gestureBoxCanvas.Background = System.Windows.Media.Brushes.Black;
            gestureBoxCanvas.Opacity = 25;
            gestureBoxCanvas.Margin = new System.Windows.Thickness(10, 0, 10, 10);

            gestureBoxHost.Child = gestureBoxCanvas;

            Point hipLeftPoint = new Point(257, 223);
            Point shoulderLeftPoint = new Point(238, 152);
            Point shoulderRightPoint = new Point(306, 152);

            // Hips
            gestureBoxCanvas.Children.Add(new System.Windows.Shapes.Polyline()   
            {
                Points = new System.Windows.Media.PointCollection() { new WinPoint(hipLeftPoint.X, hipLeftPoint.Y), new WinPoint(273, 207), new WinPoint(291, 223) },
                Stroke = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(128, 128, 255)),
                StrokeThickness = 5
            });

            // Spine
            gestureBoxCanvas.Children.Add(new System.Windows.Shapes.Polyline()
            {
                Points = new System.Windows.Media.PointCollection() { new WinPoint(273, 207), new WinPoint(275, 197), new WinPoint(272, 127), new WinPoint(272, 92) },
                Stroke = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(128, 128, 255)),
                StrokeThickness = 5
            });

            // Left Arm
            gestureBoxCanvas.Children.Add(new System.Windows.Shapes.Polyline()
            {
                Points = new System.Windows.Media.PointCollection() { new WinPoint(272, 127), new WinPoint(shoulderLeftPoint.X, shoulderLeftPoint.Y), new WinPoint(220, 205), new WinPoint(207, 260), new WinPoint(205, 280) },
                Stroke = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(128, 128, 255)),
                StrokeThickness = 5
            });

            // Right Arm
            gestureBoxCanvas.Children.Add(new System.Windows.Shapes.Polyline()
            {
                Points = new System.Windows.Media.PointCollection() { new WinPoint(272, 127), new WinPoint(shoulderRightPoint.X, shoulderRightPoint.Y), new WinPoint(327, 206), new WinPoint(340, 265), new WinPoint(342, 281) },
                Stroke = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromRgb(128, 128, 255)),
                StrokeThickness = 5
            });

            
            // Gesture Rectangles
            AddRectangle(GestureRectangleType.StartGestureRectangle, shoulderLeftPoint, GestureRectangleColorSet.MouseRectangles);
            AddRectangle(GestureRectangleType.LeftClickGestureRectangle, hipLeftPoint, GestureRectangleColorSet.MouseRectangles);
            AddRectangle(GestureRectangleType.RightClickGestureRectangle, new Point(shoulderLeftPoint.X, hipLeftPoint.Y), GestureRectangleColorSet.MouseRectangles);
            AddRectangle(GestureRectangleType.UpperGestureRectangle, shoulderLeftPoint, GestureRectangleColorSet.MouseRectangles);
            AddRectangle(GestureRectangleType.RightHandSwipeGestureRectangle, hipLeftPoint, GestureRectangleColorSet.GestureRectangles);
            AddRectangle(GestureRectangleType.LeftHandSwipeGestureRectangle, hipLeftPoint, GestureRectangleColorSet.GestureRectangles);
            AddRectangle(GestureRectangleType.CenterGestureRectangle, hipLeftPoint, GestureRectangleColorSet.GestureRectangles);
            AddRectangle(GestureRectangleType.LowerLeftGestureRectangle, hipLeftPoint, GestureRectangleColorSet.GestureRectangles);
            AddRectangle(GestureRectangleType.UpperRightGestureRectangle, shoulderRightPoint, GestureRectangleColorSet.GestureRectangles);
            
            // Adjustment Rectangle Panels
            AddRectanglePanel(GestureRectangleType.StartGestureRectangle, "Start Gesture Rectangle", 0);
            AddRectanglePanel(GestureRectangleType.LeftClickGestureRectangle, "Left Click Gesture Rectangle", 1);
            AddRectanglePanel(GestureRectangleType.RightClickGestureRectangle, "Right Click Gesture Rectangle", 2);
            AddRectanglePanel(GestureRectangleType.UpperGestureRectangle, "Upper Gesture Rectangle", 3);
            AddRectanglePanel(GestureRectangleType.RightHandSwipeGestureRectangle, "Right Swipe Gesture Rectangle", 4);
            AddRectanglePanel(GestureRectangleType.LeftHandSwipeGestureRectangle, "Left Swipe Gesture Rectangle", 5);
            AddRectanglePanel(GestureRectangleType.CenterGestureRectangle, "Center Gesture Rectangle", 6);
            AddRectanglePanel(GestureRectangleType.LowerLeftGestureRectangle, "Lower Left Gesture Rectangle", 7);
            AddRectanglePanel(GestureRectangleType.UpperRightGestureRectangle, "Upper Right Gesture Rectangle", 8);
        }

        private void AddRectangle(GestureRectangleType type, Point point, GestureRectangleColorSet colorSet)
        {
            GestureRectInitialParams initParams = GestureRectInitialParams.initialParamsDictionary[type];
            System.Windows.Shapes.Rectangle rect = new System.Windows.Shapes.Rectangle();
            rect.Stroke = new System.Windows.Media.SolidColorBrush { Color = colorSet == GestureRectangleColorSet.MouseRectangles
                                                                             ? System.Windows.Media.Colors.White
                                                                             : System.Windows.Media.Colors.DeepSkyBlue};
            rect.StrokeThickness = 4;

            rect.Width = initParams.Width;
            rect.Height = initParams.Height;
            System.Windows.Controls.Canvas.SetLeft(rect, point.X - initParams.Xmod);
            System.Windows.Controls.Canvas.SetTop(rect, point.Y - initParams.Ymod);

            gestureBoxCanvas.Children.Add(rect);
            gestureRectangles.Add(type, new GestureRectangleControl(type, rect, point, colorSet));
        }

        private void AddRectanglePanel(GestureRectangleType type, string name, int count)
        {
            Panel panel = new Panel();
            panel.Location = new Point(10, 300 + 31 * count);
            panel.Size = new Size(685, 31);
            panel.BorderStyle = BorderStyle.Fixed3D;
            panel.MouseEnter += delegate(object sender, EventArgs e) { gestureRectanglePanel_MouseEnter(type); };
            panel.MouseLeave += delegate(object sender, EventArgs e) { gestureRectanglePanel_MouseLeave(type); };

            Label nameLabel = new Label();
            nameLabel.Location = new Point(3, 6);
            nameLabel.AutoSize = true;
            nameLabel.Text = name;

            GestureRectInitialParams initParams = GestureRectInitialParams.initialParamsDictionary[type];

            Label xLabel = new Label();
            xLabel.Location = new Point(286, 6);
            xLabel.AutoSize = true;
            xLabel.Text = "X";

            TextBox xTextBox = new TextBox();
            xTextBox.Location = new Point(311, 2);
            xTextBox.Size = new Size(58, 24);
            xTextBox.Text = initParams.Xmod.ToString();
            xTextBox.TextChanged += delegate(object sender, EventArgs e) { gestureRectangleTextBoxX_TextChanged((TextBox)sender, type); };

            Label yLabel = new Label();
            yLabel.Location = new Point(388, 6);
            yLabel.AutoSize = true;
            yLabel.Text = "Y";

            TextBox yTextBox = new TextBox();
            yTextBox.Location = new Point(413, 2);
            yTextBox.Size = new Size(58, 24);
            yTextBox.Text = initParams.Ymod.ToString();
            yTextBox.TextChanged += delegate(object sender, EventArgs e) { gestureRectangleTextBoxY_TextChanged((TextBox)sender, type); };

            Label wLabel = new Label();
            wLabel.Location = new Point(490, 6);
            wLabel.AutoSize = true;
            wLabel.Text = "W";

            TextBox wTextBox = new TextBox();
            wTextBox.Location = new Point(515, 2);
            wTextBox.Size = new Size(58, 24);
            wTextBox.Text = initParams.Width.ToString();
            wTextBox.TextChanged += delegate(object sender, EventArgs e) { gestureRectangleTextBoxW_TextChanged((TextBox)sender, type); };

            Label hLabel = new Label();
            hLabel.Location = new Point(592, 6);
            hLabel.AutoSize = true;
            hLabel.Text = "H";

            TextBox hTextBox = new TextBox();
            hTextBox.Location = new Point(617, 2);
            hTextBox.Size = new Size(58, 24);
            hTextBox.Text = initParams.Height.ToString();
            hTextBox.TextChanged += delegate(object sender, EventArgs e) { gestureRectangleTextBoxH_TextChanged((TextBox)sender, type); };

            panel.Controls.AddRange(new Control[] { nameLabel, xLabel, xTextBox, yLabel, yTextBox, wLabel, wTextBox, hLabel, hTextBox });
            gestureBoxTab.Controls.Add(panel);

            gestureRectangles[type].TextBoxX = xTextBox;
            gestureRectangles[type].TextBoxY = yTextBox;
        }

        private void InitializeApplicationDockSettings()
        {
            customApps = new List<CustomApp> 
            { 
                new CustomApp(app1ComboBox, app1PictureBox, app1CustomPanel, app1ImagePathTextBox, app1AppPathTextBox, app1ImageBrowseButton, app1AppBrowseButton, app1ResizeButton, 0),
                new CustomApp(app2ComboBox, app2PictureBox, app2CustomPanel, app2ImagePathTextBox, app2AppPathTextBox, app2ImageBrowseButton, app2AppBrowseButton, app2ResizeButton, 1),
                new CustomApp(app3ComboBox, app3PictureBox, app3CustomPanel, app3ImagePathTextBox, app3AppPathTextBox, app3ImageBrowseButton, app3AppBrowseButton, app3ResizeButton, 2),
                new CustomApp(app4ComboBox, app4PictureBox, app4CustomPanel, app4ImagePathTextBox, app4AppPathTextBox, app4ImageBrowseButton, app4AppBrowseButton, app4ResizeButton, 3),
                new CustomApp(app5ComboBox, app5PictureBox, app5CustomPanel, app5ImagePathTextBox, app5AppPathTextBox, app5ImageBrowseButton, app5AppBrowseButton, app5ResizeButton, 4)
            };

            foreach (CustomApp customApp in customApps)
            {
                customApp.ComboBox.DataSource = new List<PredefinedApp>(PredefinedApp.PredefinedApps);
                customApp.ComboBox.DisplayMember = "Name";
                customApp.ComboBox.SelectedIndex = customApps.IndexOf(customApp);
                customApp.ComboBox.SelectedIndexChanged += new EventHandler(appComboBox_SelectedIndexChanged);
                customApp.ImagePathButton.Click += new EventHandler(browseImageButton_Click);
                customApp.FilePathButton.Click += new EventHandler(browseFileButton_Click);
                customApp.ResizeButton.Click += new EventHandler(appResizeButton_Click);
                customApp.CustomPanel.Hide();
                customApp.ResizeButton.Hide();
                using (FileStream fs = new FileStream((((PredefinedApp)customApp.ComboBox.SelectedItem).ImagePath), FileMode.Open, FileAccess.Read))
                {
                    customApp.PictureBox.Image = Image.FromStream(fs);
                }
            }
        }

        private void InitializeScrollBars()
        {
            CustomScrollBar scrollBarUp = new CustomScrollBar("ScrollBar", appPanel, ScrollType.Up);
            scrollBarUp.Location = new Point(0, 40);
            appDockTab.Controls.Add(scrollBarUp);

            CustomScrollBar scrollBarDown = new CustomScrollBar("ScrollBar", appPanel, ScrollType.Down);
            scrollBarDown.Location = new Point(0, 477 +76);
            appDockTab.Controls.Add(scrollBarDown);
        }

        private void InitializeCheckBoxes()
        {
            //systemStartCheckBox = new LargeCheckBox(405, 5);
            //systemStartPanel.Controls.Add(systemStartCheckBox);

            gestureControlCheckBox = new LargeCheckBox(405, 5);
            gestureControlPanel.Controls.Add(gestureControlCheckBox);

            mouseControlCheckBox = new LargeCheckBox(405, 5);
            mouseControlPanel.Controls.Add(mouseControlCheckBox);

            voiceCommandsAtStartCheckBox = new LargeCheckBox(405, 5);
            voiceCommandsAtStartPanel.Controls.Add(voiceCommandsAtStartCheckBox);

            showSkeletalTrackingCheckBox = new LargeCheckBox(405, 5);
            showSkeletalTrackingPanel.Controls.Add(showSkeletalTrackingCheckBox);

            enabledVoiceCommandCheckBox = new LargeCheckBox(618, 3);
            enabledVoiceCommandPanel.Controls.Add(enabledVoiceCommandCheckBox);
            enabledVoiceCommandCheckBox.MouseUp += delegate(object sender, MouseEventArgs e) 
                {
                    MainProgram.VoiceCommands_ToggleAllVoiceCommandsState(enabledVoiceCommandCheckBox.Checked);

                    if (enabledVoiceCommandCheckBox.Checked)
                        voiceCommandTabControl.Show();
                    else
                        voiceCommandTabControl.Hide();
                };

            voiceCommandControls = new List<VoiceCommandControl>
            {
                new VoiceCommandControl(VoiceCommandAction.Activate, new LargeCheckBox(240,3), activateTrackBar, activateConfidenceLabel, activatePanel),
                new VoiceCommandControl(VoiceCommandAction.Deactivate, new LargeCheckBox(240,3), deactivateTrackBar, deactivateConfidenceLabel, deactivatePanel),
                new VoiceCommandControl(VoiceCommandAction.Yes, new LargeCheckBox(240,3), yesTrackBar, yesConfidenceLabel, yesPanel),
                new VoiceCommandControl(VoiceCommandAction.No, new LargeCheckBox(240,3), noTrackBar, noConfidenceLabel, noPanel),

                new VoiceCommandControl(VoiceCommandAction.SystemShutdown, new LargeCheckBox(240,3), systemShutdownTrackBar, systemShutdownConfidenceLabel, systemShutdownPanel),
                new VoiceCommandControl(VoiceCommandAction.OpenSettings, new LargeCheckBox(240,3), openSettingsTrackBar, openSettingsConfidenceLabel, openSettingsPanel),
                new VoiceCommandControl(VoiceCommandAction.CloseSettings, new LargeCheckBox(240,3), closeSettingsTrackBar, closeSettingsConfidenceLabel, closeSettingsPanel),
                new VoiceCommandControl(VoiceCommandAction.OpenKeyboard, new LargeCheckBox(240,3), openKeyboardTrackBar, openKeyboardConfidenceLabel, openKeyboardPanel),
                new VoiceCommandControl(VoiceCommandAction.CloseKeyboard, new LargeCheckBox(240,3), closeKeyboardTrackBar, closeKeyboardConfidenceLabel, closeKeyboardPanel),
                new VoiceCommandControl(VoiceCommandAction.MouseControlOn, new LargeCheckBox(240,3), mouseControlOnTrackBar, mouseControlOnConfidenceLabel, mouseControlOnPanel),
                new VoiceCommandControl(VoiceCommandAction.MouseControlOff, new LargeCheckBox(240,3), mouseControlOffTrackBar, mouseControlOffConfidenceLabel, mouseControlOffPanel),
               
                new VoiceCommandControl(VoiceCommandAction.Shutdown, new LargeCheckBox(240,3), shutdownTrackBar, shutdownConfidenceLabel, shutdownPanel),
                new VoiceCommandControl(VoiceCommandAction.Logoff, new LargeCheckBox(240,3), logoffTrackBar, logoffConfidenceLabel, logoffPanel),
                new VoiceCommandControl(VoiceCommandAction.Restart, new LargeCheckBox(240,3), restartTrackBar, restartConfidenceLabel, restartPanel),
                new VoiceCommandControl(VoiceCommandAction.Hibernate, new LargeCheckBox(240,3), hibernateTrackBar, hibernateConfidenceLabel, hibernatePanel),
                new VoiceCommandControl(VoiceCommandAction.LockComputer, new LargeCheckBox(240,3), lockComputerTrackBar, lockComputerConfidenceLabel, lockComputerPanel),
                new VoiceCommandControl(VoiceCommandAction.Minimize, new LargeCheckBox(240,3), minimizeTrackBar, minimizeConfidenceLabel, minimizePanel),
                new VoiceCommandControl(VoiceCommandAction.Maximize, new LargeCheckBox(240,3), maximizeTrackBar, maximizeConfidenceLabel, maximizePanel),

                new VoiceCommandControl(VoiceCommandAction.ShowDesktop, new LargeCheckBox(240,3), showDesktopTrackBar, showDesktopConfidenceLabel, showDesktopPanel),
                new VoiceCommandControl(VoiceCommandAction.CloseWindow, new LargeCheckBox(240,3), closeWindowTrackBar, closeWindowConfidenceLabel, closeWindowPanel),
                new VoiceCommandControl(VoiceCommandAction.WindowSwitcher, new LargeCheckBox(240,3), windowSwitcherTrackBar, windowSwitcherConfidenceLabel, windowSwitcherPanel),
                new VoiceCommandControl(VoiceCommandAction.Search, new LargeCheckBox(240,3), searchTrackBar, searchConfidenceLabel, searchPanel),

                new VoiceCommandControl(VoiceCommandAction.ApplicationOne, new LargeCheckBox(240,3), app1TrackBar, app1ConfidenceLabel, app1Panel),
                new VoiceCommandControl(VoiceCommandAction.ApplicationTwo, new LargeCheckBox(240,3), app2TrackBar, app2ConfidenceLabel, app2Panel),
                new VoiceCommandControl(VoiceCommandAction.ApplicationThree, new LargeCheckBox(240,3), app3TrackBar, app3ConfidenceLabel, app3Panel),
                new VoiceCommandControl(VoiceCommandAction.ApplicationFour, new LargeCheckBox(240,3), app4TrackBar, app4ConfidenceLabel, app4Panel),
                new VoiceCommandControl(VoiceCommandAction.ApplicationFive, new LargeCheckBox(240,3), app5TrackBar, app5ConfidenceLabel, app5Panel),

                new VoiceCommandControl(VoiceCommandAction.Chrome, new LargeCheckBox(240,3), chromeTrackBar, chromeConfidenceLabel, chromePanel),
                new VoiceCommandControl(VoiceCommandAction.Firefox, new LargeCheckBox(240,3), firefoxTrackBar, firefoxConfidenceLabel, firefoxPanel),
                new VoiceCommandControl(VoiceCommandAction.InternetExplorer, new LargeCheckBox(240,3), IETrackBar, IEConfidenceLabel, IEPanel)
            };

            int count = 0;
            foreach (VoiceCommandControl control in voiceCommandControls)
            {
                control.CheckBox.MouseUp += new MouseEventHandler(voiceCommandCheckbox_MouseUp);
                control.CheckBox.Tag = count;
                control.ConfidenceTrackBar.Scroll += new EventHandler(confidenceTrackBar_Scroll);
                control.ConfidenceTrackBar.MouseUp += new MouseEventHandler(confidenceTrackBar_MouseUp);
                control.ConfidenceTrackBar.Tag = count;
                control.ContainingPanel.Controls.Add(control.CheckBox);
                count++;
            }
        }

        #region SettingsForm Loading and Closing Functions
        
        private void SettingsForm_Load(object sender, EventArgs e)
        {
            // Gets the width and height of the user's screen
            int screenWidth = (int)Screen.PrimaryScreen.Bounds.Width;
            int screenHeight = (int)Screen.PrimaryScreen.Bounds.Height;

            this.DesktopLocation = new Point(screenWidth / 2 - this.Width / 2, screenHeight / 2 - this.Height / 2);
        }

        private void SettingsForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
            {
                // Cancel the close and hide the form
                e.Cancel = true;
                this.Hide();
            }
        }

        #endregion

        #region App Dock Tab Settings
        
        private void appComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            ComboBox appComboBox = (ComboBox)sender;
            string imagePath = ((PredefinedApp)appComboBox.SelectedItem).ImagePath;

            CustomApp customApp = customApps[(int)appComboBox.Tag];

            if (!String.IsNullOrEmpty(imagePath))
            {
                customApp.PictureBox.Image = Image.FromFile(imagePath);
                customApp.CustomPanel.Hide();
                customApp.ImagePathTextBox.Text = String.Empty;
                customApp.FilePathTextBox.Text = String.Empty;

            }
            else
            {
                customApp.PictureBox.Image = null;
                customApp.CustomPanel.Show();
            }

        }

        private void browseImageButton_Click(object sender, EventArgs e)
        {
            DialogResult result = browseImageDialog.ShowDialog();
            if (result == DialogResult.OK)
            {
                if (System.IO.File.Exists(browseImageDialog.FileName))
                {
                    FileInfo fileInfo = new FileInfo(browseImageDialog.FileName);
                    if (acceptedImageTypes.Where(x => x == fileInfo.Extension).Any())
                    {
                        Button browseButton = (Button)sender;
                        CustomApp customApp = customApps[(int)browseButton.Tag];

                        customApp.ImagePathTextBox.Text = browseImageDialog.FileName;

                        using (FileStream fs = new FileStream(browseImageDialog.FileName, FileMode.Open, FileAccess.Read))
                        {
                            customApp.PictureBox.Image = Image.FromStream(fs);
                            customApp.ResizeButton.Hide();
                        }
                    }
                }
            }
        }

        private void browseFileButton_Click(object sender, EventArgs e)
        {
            Button browseButton = (Button)sender;
            CustomApp customApp = customApps[(int)browseButton.Tag];

            customApp.ResizeButton.Hide();

            DialogResult result = browseFileDialog.ShowDialog();
            if (result == DialogResult.OK)
            {
                if (System.IO.File.Exists(browseFileDialog.FileName))
                {
                    customApp.FilePathTextBox.Text = browseFileDialog.FileName;

                    Icons icons = new Icons(Icons.SystemImageListSize.JumboIcons);

                    Icon fileIcon = icons.GetIcon(browseFileDialog.FileName);

                    customApp.PictureBox.Image = fileIcon.ToBitmap();

                    icons.Dispose();

                    customApp.ImagePathTextBox.Text = String.Empty;
                    customApp.ResizeButton.Show();
                }
            }
        }

        private void appResizeButton_Click(object sender, EventArgs e)
        {
            CustomApp customApp = customApps[(int)((Button)sender).Tag];

            if (customApp.FilePathTextBox.Text != String.Empty && customApp.PictureBox.Image != null && customApp.ComboBox.SelectedIndex == 5)
            {
                Icons icons = new Icons(Icons.SystemImageListSize.LargeIcons);
                Icon fileIcon = icons.GetIcon(customApp.FilePathTextBox.Text);
                customApp.PictureBox.Image = fileIcon.ToBitmap();
                icons.Dispose();
                customApp.ResizeButton.Hide();
            }
        }

        private bool VerifyCustomApp()
        {
            // Verify custom app paths
            foreach (CustomApp customApp in customApps)
            {
                if (customApp.ComboBox.SelectedIndex == customApp.ComboBox.Items.Count - 1)
                {
                    if (!System.IO.File.Exists(customApp.FilePathTextBox.Text))
                    {
                        MessageBox.Show("Application " + customApps.IndexOf(customApp) + 1 + " application path is invalid.");
                        return false;
                    }
                    if (!System.IO.File.Exists(customApp.ImagePathTextBox.Text) && !String.IsNullOrEmpty(customApp.ImagePathTextBox.Text))
                    {
                        MessageBox.Show("Application " + customApps.IndexOf(customApp) + 1 + " image path is invalid.");
                        return false;
                    }
                }
            }

            return true;
        }

        private void SetCustomApps()
        {
            foreach (CustomApp customApp in customApps)
            {
                int appIndex = customApps.IndexOf(customApp) + 1;

                // Delete old image for app if it exists
                string oldImage = imageFolder + settingsINI.IniReadValue("App" + appIndex, "imageName");
                if (System.IO.File.Exists(oldImage))
                {
                    FileSystem.DeleteFile(oldImage);
                }

                if (customApp.ComboBox.SelectedIndex == customApp.ComboBox.Items.Count - 1)
                {
                    if (System.IO.File.Exists(customApp.ImagePathTextBox.Text))
                    {
                        FileInfo fileInfo = new FileInfo(customApp.ImagePathTextBox.Text);

                        customApp.ImageName = "AppImage" + appIndex + "_" + fileInfo.Name;
                        FileSystem.CopyFile(fileInfo.FullName, imageFolder + customApp.ImageName);
                    }
                    else if (System.IO.File.Exists(customApp.FilePathTextBox.Text))
                    {
                        FileInfo fileInfo = new FileInfo(customApp.FilePathTextBox.Text);

                        customApp.ImageName = "AppImage" + appIndex + "_" + fileInfo.Name.Substring(0, fileInfo.Name.LastIndexOf(".")) + ".png";
                        string createPath = imageFolder + customApp.ImageName;

                        using (FileStream imageStream = new FileStream(createPath, FileMode.Create))
                        {
                            customApp.PictureBox.Image.Save(imageStream, ImageFormat.Png);
                        }
                    }
                }
            }
        }

        private void resetAppsButton_Click(object sender, EventArgs e)
        {
            foreach (CustomApp customApp in customApps)
            {
                customApp.ComboBox.SelectedIndex = customApps.IndexOf(customApp);
            }
        }
        #endregion

        #region Kinect Tab Settings
        
        private void setKinectTiltButton_Click(object sender, EventArgs e)
        {
            if (kinectTiltUpDown.Value > 27)
                kinectTiltUpDown.Value = 27;
            else if (kinectTiltUpDown.Value < -27)
                kinectTiltUpDown.Value = -27;

            int value = (int)kinectTiltUpDown.Value;

            // perform tilt
            MainProgram.KinectForm_AdjustElevation(value);
        }
        #endregion

        private void systemShutdownButton_Click(object sender, EventArgs e)
        {
            MainProgram.ShutDown(); // Kills the rest of the application
        }

        private void saveSettingsButton_Click(object sender, EventArgs e)
        {
            if (!VerifyCustomApp())
                return;

            SetCustomApps();

            //Write the data to the settings ini file
            writeSettingsToINI();

            // Refresh voice commands
            MainProgram.VoiceCommands_Reset();

            // Refresh the AppDock
            MainProgram.AppDock_Refresh();
        }

        private void writeSettingsToINI()
        {
            //settingsINI.IniWriteValue("General", "systemStart", systemStartCheckBox.Checked.ToString());
            settingsINI.IniWriteValue("General", "gestureControlOnStart", gestureControlCheckBox.Checked.ToString());
            settingsINI.IniWriteValue("General", "mouseControlOnStart", mouseControlCheckBox.Checked.ToString());
            settingsINI.IniWriteValue("General", "voiceCommandsStart", voiceCommandsAtStartCheckBox.Checked.ToString());
            settingsINI.IniWriteValue("General", "showSkeletalTracking", showSkeletalTrackingCheckBox.Checked.ToString());
            settingsINI.IniWriteValue("Voice Control", "keyword", voiceCommandKeywordTextBox.Text);
            settingsINI.IniWriteValue("Voice Control", "enabledVoiceCommands", enabledVoiceCommandCheckBox.Checked.ToString());

            foreach (VoiceCommandControl control in voiceCommandControls)
            {
                string command = MainProgram.VoiceCommands_GetVoiceCommandString(control.Action).Replace(" ", string.Empty);
                settingsINI.IniWriteValue("Voice Control", command, control.CheckBox.Checked.ToString());
                settingsINI.IniWriteValue("Voice Control", command + "Confidence", control.ConfidenceTrackBar.Value.ToString());
            }
            
            foreach (CustomApp customApp in customApps)
            {
                int appIndex = customApps.IndexOf(customApp) + 1;

                settingsINI.IniWriteValue("App" + appIndex, "type", ((PredefinedApp)customApp.ComboBox.SelectedItem).Type.ToString());

                if (customApp.ComboBox.SelectedIndex == customApp.ComboBox.Items.Count - 1)
                {
                    settingsINI.IniWriteValue("App" + appIndex, "filePath", customApp.FilePathTextBox.Text);
                    settingsINI.IniWriteValue("App" + appIndex, "imageName", customApp.ImageName);
                }
                else
                {
                    settingsINI.IniWriteValue("App" + appIndex, "filePath", String.Empty);
                    settingsINI.IniWriteValue("App" + appIndex, "imageName", String.Empty);
                }
            }

            // Write Gesture Box Data
            foreach (GestureRectangleControl control in gestureRectangles.Values)
            {
                settingsINI.IniWriteValue("Gesture Boxes", control.Type.ToString() + "X", control.TextBoxX.Text);
                settingsINI.IniWriteValue("Gesture Boxes", control.Type.ToString() + "Y", control.TextBoxY.Text);
                settingsINI.IniWriteValue("Gesture Boxes", control.Type.ToString() + "W", control.Rectangle.Width.ToString());
                settingsINI.IniWriteValue("Gesture Boxes", control.Type.ToString() + "H", control.Rectangle.Height.ToString());

                int xmod;
                if (Int32.TryParse(control.TextBoxX.Text, out xmod))
                    GestureRectInitialParams.initialParamsDictionary[control.Type].Xmod = xmod;

                int ymod;
                if (Int32.TryParse(control.TextBoxY.Text, out ymod))
                    GestureRectInitialParams.initialParamsDictionary[control.Type].Ymod = ymod;

                GestureRectInitialParams.initialParamsDictionary[control.Type].Width = (int)control.Rectangle.Width;
                GestureRectInitialParams.initialParamsDictionary[control.Type].Height = (int)control.Rectangle.Height;
            }
        }

        private void readSettingsFromINI()
        {
            //systemStartCheckBox.Checked = Boolean.Parse(settingsINI.IniReadValue("General", "systemStart"));
            gestureControlCheckBox.Checked = Boolean.Parse(settingsINI.IniReadValue("General", "gestureControlOnStart"));
            mouseControlCheckBox.Checked = Boolean.Parse(settingsINI.IniReadValue("General", "mouseControlOnStart"));
            voiceCommandsAtStartCheckBox.Checked = Boolean.Parse(settingsINI.IniReadValue("General", "voiceCommandsStart"));
            showSkeletalTrackingCheckBox.Checked = Boolean.Parse(settingsINI.IniReadValue("General", "showSkeletalTracking"));
            voiceCommandKeywordTextBox.Text = settingsINI.IniReadValue("Voice Control", "keyword");
            enabledVoiceCommandCheckBox.Checked = Boolean.Parse(settingsINI.IniReadValue("Voice Control", "enabledVoiceCommands"));

            // if voice commands are not enabled, hide the voice command tab control
            if (!enabledVoiceCommandCheckBox.Checked)
                voiceCommandTabControl.Hide();

            foreach (VoiceCommandControl control in voiceCommandControls)
            {
                string command = MainProgram.VoiceCommands_GetVoiceCommandString(control.Action).Replace(" ", string.Empty);
                control.CheckBox.Checked = Boolean.Parse(settingsINI.IniReadValue("Voice Control", command));

                string confidence = settingsINI.IniReadValue("Voice Control", command + "Confidence");
                control.ConfidenceTrackBar.Value = Int32.Parse(confidence);
                control.ConfidenceLabel.Text = confidence;
            }
                
            showSkeletalWindowButton.Text = showSkeletalTrackingCheckBox.Checked ? "Hide" : "Show";

            foreach (CustomApp customApp in customApps)
            {
                int appIndex = customApps.IndexOf(customApp) + 1;

                customApp.ComboBox.SelectedIndex = (int)((PredefinedAppType)PredefinedAppType.Parse(typeof(PredefinedAppType), settingsINI.IniReadValue("App" + appIndex, "type")));

                if (customApp.ComboBox.SelectedIndex == (int)PredefinedAppType.CustomApplication)
                {
                    customApp.FilePathTextBox.Text = settingsINI.IniReadValue("App" + appIndex, "filePath");

                    string imageText = Constants.InterfaceImagesFolder + settingsINI.IniReadValue("App" + appIndex, "imageName");
                    string imagePath = System.IO.File.Exists(imageText) ? imageText : Constants.InterfaceImagesFolder + "defaultIcon.png";

                    using (FileStream fs = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
                    {
                        customApp.PictureBox.Image = Image.FromStream(fs);
                    }
                }

                else
                {
                    string image = String.Empty;

                    switch (customApp.ComboBox.SelectedIndex)
                    {
                        case (int)PredefinedAppType.MicrosoftWord: { image = Constants.WordIconImage; break; }
                        case (int)PredefinedAppType.MicrosoftPowerPoint: { image = Constants.PowerPointIconImage; break; }
                        case (int)PredefinedAppType.KinectKeyboard: { image = Constants.KeyboardIconImage; break; }
                        case (int)PredefinedAppType.KinectMediaPlayer: { image = Constants.KinectMediaPlayerIconImage; break; }
                        case (int)PredefinedAppType.KinectFolderControl: { image = Constants.FolderControlIconImage; break; }
                    }
                    string imagePath = System.IO.File.Exists(image) ? image : Constants.InterfaceImagesFolder + "defaultIcon.png";

                    using (FileStream fs = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
                    {
                        customApp.PictureBox.Image = Image.FromStream(fs);
                    }
                }
            }
        }

        #region Scroll Methods
        
        #endregion

        private void resetControlBoardButton_Click(object sender, EventArgs e)
        {
            MainProgram.ControlForm_ResetLocation();
        }

        private void resetDockLocationButton_Click(object sender, EventArgs e)
        {
            MainProgram.AppDock_ResetLocation();
        }

        private void showControlBoardButton_Click(object sender, EventArgs e)
        {
            MainProgram.ControlForm_ToggleVisibility();
        }

        private void showAppDockButton_Click(object sender, EventArgs e)
        {
            MainProgram.AppDock_ToggleVisibility();
        }

        private void showSkeletalWindowButton_Click(object sender, EventArgs e)
        {
            MainProgram.KinectForm_ToggleSkeletalWindowVisibility();
        }

        private void confidenceTrackBar_Scroll(object sender, EventArgs e)
        {
            VoiceCommandControl control = voiceCommandControls[((int)((TrackBar)sender).Tag)];

            control.ConfidenceLabel.Text = control.ConfidenceTrackBar.Value.ToString();
        }

        private void confidenceTrackBar_MouseUp(object sender, MouseEventArgs e)
        {
            VoiceCommandControl control = voiceCommandControls[((int)((TrackBar)sender).Tag)];

            MainProgram.VoiceCommands_SetVoiceCommandConfidence(control.Action, control.ConfidenceTrackBar.Value);
        }

        private void voiceCommandCheckbox_MouseUp(object sender, MouseEventArgs e)
        {
            VoiceCommandControl control = voiceCommandControls[((int)((LargeCheckBox)sender).Tag)];

            MainProgram.VoiceCommands_SetVoiceCommandActive(control.Action, control.CheckBox.Checked);
        }

        private void gestureRectangleTextBoxX_TextChanged(TextBox textBox, GestureRectangleType type)
        {
            int xmod;
            if (!Int32.TryParse(textBox.Text, out xmod))
                return;

            GestureRectangleControl control = gestureRectangles[type];
            System.Windows.Controls.Canvas.SetLeft(control.Rectangle, control.InitialPoint.X - xmod);
        }

        private void gestureRectangleTextBoxY_TextChanged(TextBox textBox, GestureRectangleType type)
        {
            int ymod;
            if (!Int32.TryParse(textBox.Text, out ymod))
                return;

            GestureRectangleControl control = gestureRectangles[type];
            System.Windows.Controls.Canvas.SetTop(control.Rectangle, control.InitialPoint.Y - ymod);
        }

        private void gestureRectangleTextBoxW_TextChanged(TextBox textBox, GestureRectangleType type)
        {
            int width;
            if (!Int32.TryParse(textBox.Text, out width))
                return;
            if (width < 0)
                return;

            gestureRectangles[type].Rectangle.Width = width;
        }

        private void gestureRectangleTextBoxH_TextChanged(TextBox textBox, GestureRectangleType type)
        {
            int height;
            if (!Int32.TryParse(textBox.Text, out height))
                return;
            if (height < 0)
                return;

            gestureRectangles[type].Rectangle.Height = height;
        }

        private void gestureRectanglePanel_MouseEnter(GestureRectangleType type)
        {
            GestureRectangleControl control = gestureRectangles[type];

            control.Rectangle.Stroke = new System.Windows.Media.SolidColorBrush
            {
                Color = control.ColorSet == GestureRectangleColorSet.MouseRectangles
                                            ? System.Windows.Media.Colors.Yellow
                                            : System.Windows.Media.Colors.Green
            };
        }

        private void gestureRectanglePanel_MouseLeave(GestureRectangleType type)
        {
            GestureRectangleControl control = gestureRectangles[type];

            control.Rectangle.Stroke = new System.Windows.Media.SolidColorBrush
            {
                Color = control.ColorSet == GestureRectangleColorSet.MouseRectangles
                                            ? System.Windows.Media.Colors.White
                                            : System.Windows.Media.Colors.DeepSkyBlue
            };
        }

        private void resetGestureBoxesButton_Click(object sender, EventArgs e)
        {
            foreach (GestureRectangleControl control in gestureRectangles.Values)
            {
                control.TextBoxX.Text = settingsINI.IniReadValue("Initial Gesture Boxes", "initial" + control.Type.ToString() + "X");
                control.TextBoxY.Text = settingsINI.IniReadValue("Initial Gesture Boxes", "initial" + control.Type.ToString() + "Y");
                control.Rectangle.Width = Double.Parse(settingsINI.IniReadValue("Initial Gesture Boxes", "initial" + control.Type.ToString() + "W"));
                control.Rectangle.Height = Double.Parse(settingsINI.IniReadValue("Initial Gesture Boxes", "initial" + control.Type.ToString() + "H"));
            }
        }
    }

    public class CustomApp
    {
        public string ImageName { get; set; }
        public ComboBox ComboBox { get; set; }
        public PictureBox PictureBox { get; set; }
        public Panel CustomPanel { get; set; }
        public TextBox ImagePathTextBox { get; set; }
        public TextBox FilePathTextBox { get; set; }
        public Button ImagePathButton { get; set; }
        public Button FilePathButton { get; set; }
        public Button ResizeButton { get; set; }

        public CustomApp(ComboBox comboBox, PictureBox pictureBox, Panel customPanel, TextBox imagePathTextBox,
                        TextBox filePathTextBox, Button imagePathButton, Button filePathButton, Button resizeButton, int index)
        {
            ComboBox = comboBox;
            ComboBox.Tag = index;

            PictureBox = pictureBox;
            PictureBox.Tag = index;

            CustomPanel = customPanel;
            CustomPanel.Tag = index;

            ImagePathTextBox = imagePathTextBox;
            ImagePathTextBox.Tag = index;

            FilePathTextBox = filePathTextBox;
            FilePathTextBox.Tag = index;

            ImagePathButton = imagePathButton;
            ImagePathButton.Tag = index;

            FilePathButton = filePathButton;
            FilePathButton.Tag = index;

            ResizeButton = resizeButton;
            ResizeButton.Tag = index;
        }
    }

    public class VoiceCommandControl
    {
        public VoiceCommandAction Action { get; set; }
        public LargeCheckBox CheckBox { get; set; }
        public TrackBar ConfidenceTrackBar { get; set; }
        public Label ConfidenceLabel { get; set; }
        public Panel ContainingPanel { get; set; }

        public VoiceCommandControl(VoiceCommandAction action, LargeCheckBox checkBox, TrackBar confidenceTrackBar, Label confidenceLabel, Panel containingPanel)
        {
            Action = action;
            CheckBox = checkBox;
            ConfidenceTrackBar = confidenceTrackBar;
            ConfidenceLabel = confidenceLabel;
            ContainingPanel = containingPanel;
        }
    }

    public class GestureRectangleControl
    {
        public GestureRectangleType Type { get; set; }
        public System.Windows.Shapes.Rectangle Rectangle { get; set; }
        public Point InitialPoint { get; set; }
        public GestureRectangleColorSet ColorSet { get; set; }
        public TextBox TextBoxX { get; set; }
        public TextBox TextBoxY { get; set; }

        public GestureRectangleControl(GestureRectangleType type, System.Windows.Shapes.Rectangle rect, Point point, GestureRectangleColorSet colorSet)
        {
            Type = type;
            Rectangle = rect;
            InitialPoint = point;
            ColorSet = colorSet;
        }
    }
}
